/* ************************************************
 * Experiment phase
 *
 * experiment.pde
 * ------------------------------------------------
 */


class Averager
{
	float run;
	int count;
	
	Averager()
	{
		run = 0.0;
		count = 0;
	}
	
	float getAverage()
	{
		if (count > 0)
		{
			return run / (float) count;
		}
		else
		{
			return 0.0;
		}
	}
	
	void add( float x )
	{
		run += x;
		count++;
	}
}

class Experiment
{
	int currentTask;
	StimuliList tasks;
	
	// summary
	Averager graphCountChildren;
	Averager graphLargestChildren;
	Averager graphSharedParent;
	
	Averager icicleCountChildren;
	Averager icicleLargestChildren;
	Averager icicleSharedParent;
	
	int endTimestamp;
		
	Experiment(StimuliList _tasks)
	{
		tasks = _tasks;
		currentTask = -1;
		endTimestamp = -1;
		
		// prepare averagers
		graphCountChildren = new Averager();
		graphLargestChildren = new Averager();
		graphSharedParent = new Averager();

		icicleCountChildren = new Averager();
		icicleLargestChildren = new Averager();
		icicleSharedParent = new Averager();
	}
	
	boolean render()
	{
		if (currentTask == -1)
		{
			if (millis() > 3000) {
				currentTask = 0;
			}
			else
			{
				background( QUESTION_BACKGROUND );
				fill(255); noStroke();
				ellipse( width / 2, height / 2, 40, 40 );				
			}
			
			return false;
		}
		
		else if (currentTask == tasks.size())
		{
			if (endTimestamp == -1) {
				endTimestamp = millis();
			}
			
			background( QUESTION_BACKGROUND );
			textFont( fontQuestion );
			textAlign(CENTER, CENTER);
			
			fill( QUESTION_FOREGROUND );
			stroke( QUESTION_FOREGROUND );
			
			text("Thank you!", width/2, height/2);
						
			return true;
			
		}
		else
		{
			boolean taskDone = tasks.get( currentTask ).render();
			if (taskDone)
			{
				currentTask++;
			}
			return false;
		}
	}
	
	String printTaskType(int taskType)
	{
		switch (taskType)
		{
		case TASK_COUNT_CHILDREN:
			return "count children";
		case TASK_LARGEST_CHILDREN:
			return "find largest # of children";
		case TASK_SHARED_PARENT:
			return "find shared parent";
		case TASK_BINARY_ANSWER:
			return "binary answer";
		}
		return "";
	}
	
	void writeResults(String filename)
	{
		ArrayList<String> data = new ArrayList<String>();
		
		for (int i = 0; i < tasks.size(); i++)
		{
			Stimulus task = tasks.get( i );
			
			// add stimulus data
			data.add("Name\t\t\t= " + task.name);
			data.add("Representation\t\t= " + (task.drawMode == DRAW_MODE_GRAPH ? "graph" : (task.drawMode == DRAW_MODE_TREEMAP ? "treemap" : "icicle")));
			data.add("Question\t\t= " + task.question);
			data.add("Task type\t\t= " + printTaskType( task.taskType ));
			data.add("");
			data.add("Response\t\t= " + task.strResponse);
			data.add("Actual\t\t\t= " + task.answer);
			data.add("");
			data.add("Reasoning time\t\t = " + task.reasonTime);
			data.add("Reading time\t\t = " + task.readTime);
			data.add("====================");
			data.add("");
			
			//addToSummary(task);
		}
		
		// add summary information
		/*
		data.add("\n\n");
		data.add("Summary");
		data.add("=======");
		
		data.add("AVG graph count children:\t\t " + graphCountChildren.getAverage());
		data.add("AVG graph shared parent:\t\t " +  graphSharedParent.getAverage());
		data.add("AVG graph largest # of children:\t " + graphLargestChildren.getAverage());
		
		data.add("");
		
		data.add("AVG icicle count children:\t\t " +        icicleCountChildren.getAverage());
		data.add("AVG icicle shared parent:\t\t " +         icicleSharedParent.getAverage());
		data.add("AVG icicle largest # of children:\t " + icicleLargestChildren.getAverage());
		*/
		
		writeToFile(data, filename);
	}
	
	void writeLog(String filename)
	{
		ArrayList<String> data = new ArrayList<String>();
		
		for (int i = 0; i < tasks.size(); i++)
		{
			
			Stimulus task = tasks.get( i );
			data.add("");
			data.add("Stimulus\t" + task.number);
			data.add("\t" + formatMillis( task.questionTimestamp ) + "\t\t\tquestion shown");
			data.add("\t" + formatMillis( task.visTimestamp ) + "\t\t\tvis shown");
			data.add("\t" + formatMillis( task.responseTimestamp ) + "\t\t\tresponse received");
		}
		
		data.add("");
		data.add("END");
		data.add( formatMillis( endTimestamp ) );
		
		writeToFile(data, filename);
	}
	
	void writeMachineResults(String filename)
	{
		tasks.sort();
		ArrayList<String> data = new ArrayList<String>();

		for (int i = 0; i < tasks.size(); i++)
		{
			Stimulus task = tasks.get( i );
		  	String entry =
		  	
		  		"Stimulus\t" + task.number + "\t" + 
		  		task.readTime + "\t" + 
		  		task.reasonTime + "\t" + 
		  		task.strResponse + "\t" +
		  		(task.strResponse.compareToIgnoreCase( task.answer ) == 0 ? "correct" : "wrong");
		  		
		  	data.add( entry );
		}
		writeToFile( data, filename);
	}
	
	String formatMillis( int number )
	{
		int x = number / 1000;
		int y = number % 1000;
		
		return "" + x + "." + y;
	}
	
	
	void addToSummary(Stimulus task)
	{
		// average
		switch (task.drawMode)
		{
		case DRAW_MODE_GRAPH:
			
			switch (task.taskType)
			{
				case TASK_COUNT_CHILDREN:
				graphCountChildren.add( task.reasonTime );
				break;
				
			case TASK_LARGEST_CHILDREN:
				graphLargestChildren.add( task.reasonTime );
				break;
			
			case TASK_SHARED_PARENT:
				graphSharedParent.add( task.reasonTime );
				break;
			}
			break;
			
		default:
			
			switch (task.taskType)
			{
			case TASK_COUNT_CHILDREN:
				icicleCountChildren.add( task.reasonTime );
				break;
				
			case TASK_LARGEST_CHILDREN:
				icicleLargestChildren.add( task.reasonTime );
				break;
			
			case TASK_SHARED_PARENT:
				icicleSharedParent.add( task.reasonTime );
				break;
			}
			break;
		}
	}
	
	void writeToFile(ArrayList<String> data, String filename)
	{
		String[] rawData = new String[ data.size() ];
		for (int i = 0; i < data.size(); i++)
		{
			rawData[i] = data.get(i);
		}
		saveStrings(filename, rawData);
	}
	
	void keyPressed()
	{
		if (currentTask < tasks.size() && currentTask >= 0)
		{
			tasks.get( currentTask ).keyPressed();
		}
	}
}

